# coding: utf-8

from __future__ import absolute_import, division, print_function, unicode_literals

from string import Template

from apitest.cmd.generate import GenCode
from apitest.cmd.generate_model import Thrift2py
from apitest.cmd.output import OutFileType, out_file_path


class ServiceCodeTemplate:
    _service_string = """from pydantic import Extra
from apitest.engine.baseapi import BaseService
from apitest.engine.const.enums import RType, Method
from apitest.engine.const.model import EnvModel, PSMAuth
from apitest.engine.parse import build_request, build_response

from api.$psm_name import model
from api.$psm_name.route import $route_class

PSM = "$psm"


class $service_class(BaseService):

    def __init__(self, auth:  PSMAuth = None, Env: EnvModel = None, rtype: RType = RType.obj, **kwargs):
        super($service_class, self).__init__(psm=PSM, auth=auth, Env=Env, **kwargs)
        self.rtype = rtype
"""

    _service_string_new = """from pydantic import Extra
from apitest.engine.client.http import HttpClient
from apitest.engine.const.enums import RType, Method
from apitest.engine.const.model import Auth, EnvModel
from apitest.engine.parse import build_request, build_response

from api.$psm_name import model
from api.$psm_name.route import $route_class

PSM = "$psm"


class $service_class(HttpClient):

    def __init__(self, app: str, auth: Auth = Auth(), env: EnvModel = None, rtype: RType = RType.obj, **kwargs):
        super($service_class, self).__init__(app=app, psm=PSM, auth=auth, env=env, **kwargs)
        self.rtype = rtype
"""

    _method_string = """
    @build_request(Method.$method_upper)
    def $method_name(self, rtype: RType = None, extra: Extra = Extra.ignore, **kwargs):
        rtype = rtype or self.rtype
        resp = self.client.$method($route_class.$route_name, **kwargs)
        resp = build_response(resp, model.$resp, rtype, extra)
        return resp
"""

    @property
    def service_string(self):
        return self._service_string

    @property
    def service_string_new(self):
        return self._service_string_new

    @property
    def method_string(self):
        return self._method_string


class RouteCodeTemplate:
    _class_string = """class $route_class:"""

    _route_string = """
    $route_name = \"$route\""""

    @property
    def class_string(self):
        return self._class_string

    @property
    def route_string(self):
        return self._route_string


class GenHttpCode(GenCode):

    def __init__(self, psm, idl, out_dir, is_new=True):
        super(GenHttpCode, self).__init__(psm=psm, idl=idl, out_dir=out_dir)
        self.thrift.parse_route()
        self.service_mate = self.thrift.service_mate
        self.route_class = self.psm.title().replace("_", "").replace(".", "") + "Route"
        self.is_new = is_new

    def generate_http_client(self):
        out = out_file_path(self.out_dir, OutFileType.http_client)
        service_tmp = ServiceCodeTemplate()
        service_content = ""
        psm_name = self.psm.replace(".", "_")
        for service, values in self.service_mate.items():
            if self.is_new:
                service_tmp_string = Template(service_tmp.service_string_new)
            else:
                service_tmp_string = Template(service_tmp.service_string)
            service_content += service_tmp_string.substitute(
                {"psm_name": psm_name, "psm": self.psm, "route_class": self.route_class, "service_class": service})
            for value in values:
                service_content += Template(service_tmp.method_string).substitute(
                    {"method_name": value["method_name"], "method_upper": value["method"].upper(),
                     "method": value["method"], "resp": value["resp"], "route_class": self.route_class,
                     "route_name": value["route_name"]})
        with open(out, "w", encoding='utf8') as f:
            f.write(service_content)
            f.close()

    def generate_http_route(self):
        out = out_file_path(self.out_dir, OutFileType.http_route)
        route_tmp = RouteCodeTemplate()
        route_content = ""
        route_tmp_string = Template(route_tmp.class_string)
        route_content += route_tmp_string.substitute({"route_class": self.route_class})
        for service, values in self.service_mate.items():
            for value in values:
                route_content += Template(route_tmp.route_string).substitute(
                    {"route_name": value["route_name"], "route": value["route"]})

        with open(out, "w", encoding='utf8') as f:
            f.write(route_content + "\n")
            f.close()

    def generate_https_model(self):
        out = out_file_path(self.out_dir, OutFileType.http_model)
        Thrift2py(filename=self.thrift.new_idl, prefix="", out=out, need_service=False).output()
